/*
    Copyright (c) 2007-2008 by Mikhail Borbot <mike_n@hotbox.ru>

    This file is part of mlog

    mlog is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    mlog is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with mlog.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "log_system.h"

mlog::cmodule_logger g_log1("log1", 1);
mlog::cmodule_logger_itf& log1 = g_log1;
mlog::cmodule_logger g_log2("log2", 2);
mlog::cmodule_logger_itf& _log2 = g_log2;
mlog::cmodule_logger g_log3("log3", 3);
mlog::cmodule_logger_itf& log3 = g_log3;

void run_tests();

// number of memory allocations
int g_allocations = 0;

#if defined(_DEBUG) && defined(_WIN32)
// memory allocation hook, which simply counts number of memory allocations and reallocations
int alloc_hook(int nAllocType, void *, size_t, int nBlockUse, long, const unsigned char *, int)
{
	if (nBlockUse == _CRT_BLOCK)
		return 1;
	if (nAllocType == _HOOK_ALLOC || nAllocType == _HOOK_REALLOC)
		g_allocations ++;
	return 1;
}
#endif

int main(int, char*[])
{
#if defined(_DEBUG) && defined(_WIN32)
	// start memory checking facilities
	::_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
	::_CrtSetAllocHook(alloc_hook);
#endif
	typedef mlog::cmodule_logger::sink_ptr sink_t;
	// create several sinks with different formats and filters
	// constant file1.log
	sink_t file1(new mlog::const_cfile_sink("file1"));
	file1->add_filter(mlog::or_filter(mlog::module_is<char>(1), mlog::module_is<char>(2)));
	file1->set_format(mlog::cformat() << mlog::fp_module_id <<
		'[' << std::setw(8) << std::setfill(' ') << mlog::fp_level_name << "] " <<
		mlog::fp_file_short << '@' << mlog::fp_line << '#' << mlog::fp_thread << ": "
		<< mlog::fp_message << " * " << mlog::fp_minute << ':' << mlog::fp_second << ':' << mlog::fp_milli << std::endl);
	// rotated by size 40kb * 10 file2.log
	sink_t file2(new mlog::size_cfile_sink(40960, 10, "file2"));
	file2->add_filter(mlog::or_filter(mlog::module_is<char>(2), mlog::module_is<char>(3)));
	file2->set_format(mlog::cformat() << mlog::fp_module_id <<
		'{' << std::setw(8) << std::setfill(' ') << mlog::fp_level_name << "} " <<
		mlog::fp_month << mlog::fp_day << ": " << mlog::fp_message << " # " << mlog::fp_thread <<
		" * " << mlog::fp_minute << ':' << mlog::fp_second << ':' << mlog::fp_milli << std::endl);
	// daily rotated file3.log
	sink_t file3(new mlog::day_cfile_sink("file3"));
	file3->add_filter(mlog::or_filter(mlog::module_is<char>(1), mlog::module_is<char>(3)));
	file3->set_format(mlog::cformat() << mlog::fp_module_id <<
		'<' << std::setw(8) << std::setfill(' ') << mlog::fp_level_name << "> " <<
		mlog::tag("global-state") << '#' << mlog::fp_thread << ": " << mlog::fp_message << ' ' <<
		mlog::fp_file_short << '@' << mlog::fp_line << std::endl);
	// const file, logs only "Hello, world!" messages
	sink_t file4(new mlog::const_cfile_sink("file4"));
	file4->add_filter(mlog::message_contains("Hello, world!"));
	file4->set_format(mlog::cformat() << mlog::fp_module_id << ": " << mlog::fp_message << std::endl);
	// console
	sink_t console(new mlog::null_sink<char>);
	console->set_format(LOG_DDMMYYYYHHMMSSMML_A << '{' << mlog::fp_module_id << '}' << std::endl);
	// add all sinks to all log modules
	g_log1.add_sink(file1).add_sink(file2).add_sink(file3).add_sink(console).add_sink(file4).set_level(mlog::warn);
	g_log2.add_sink(file1).add_sink(file2).add_sink(file3).add_sink(console).add_sink(file4).set_level(mlog::info);
	g_log3.add_sink(file1).add_sink(file2).add_sink(file3).add_sink(console).add_sink(file4).set_level(mlog::dbg);
	// test them
	run_tests();
	return 0;
}
